package gbench.appdemo.ggplot.plot;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import gbench.common.matlib.MatlibCanvas.NVec;
import gbench.common.matlib.data.DataReader.DFrame;
import gbench.appdemo.ggplot.layer.Layer;
import gbench.appdemo.ggplot.plot.panel.PanelFrame;
import gbench.appdemo.ggplot.plot.panel.PanelFrame.PlotMode;

/**
 * 绘图对象
 * @author gbench
 *
 */
public class GGplot {

    public GGplot(DFrame dataframe) {
        this.dataframe = dataframe;
    }

    public GGplot add(Layer layer) {
        layers.add(layer);
        return this;
    }

    /**
     * 获取默认的缩放比率
     * @param width 宽度
     * @param height 高度
     * @param coef 比如绘图空间比例 0.80
     * @return 默认affine
     */
    public NVec af(int width, int height,final double ratio) {
        final var xrng = new Double[] {Double.MAX_VALUE,Double.MIN_VALUE};
        final var yrng = new Double[] {Double.MAX_VALUE,Double.MIN_VALUE};
        
        for(var layer:layers) {
           if (layer.isOverlayer()) continue; // 取消掉单节点元素
           final var x = layer.get("x").rangeA();
           final var y = layer.get("y").rangeA();
           xrng[0]=Math.min(xrng[0], x[0]);
           xrng[1]=Math.max(xrng[1], x[1]);
           yrng[0]=Math.min(yrng[0], y[0]);
           yrng[1]=Math.max(yrng[1], y[1]);
        }
        
        final var xspan = (xrng[1] - xrng[0]); // x 方向跨度
        final var yspan = (yrng[1] - yrng[0]); // y 方向跨度
        final var scalex = xspan == 0 || xspan >= Double.MAX_VALUE ? 1 : width * ratio / xspan; // x 方向缩放比例
        final var scaley = yspan == 0 || xspan >= Double.MAX_VALUE ? 1 : height * ratio / yspan; // y 方向缩放比例
        final var af = NVec.of(scalex, scaley, -xrng[0] * scalex + (1 - ratio) / 2 * width,-yrng[0] * scaley + (1 - ratio) / 2 * height);
        
        return af;
    }

    /**
     * 添加一绘图面板
     * @param width 面板宽度
     * @param height 面板高度
     * @param af 坐标变换
     * @return GGplot
     */
    public GGplot addPanel(int width, int height, NVec af) {
        this.plotFrame.addPanel(width, height, af!=null?af:this.af(width, height,0.8),panel->{
            panel.setLayers(this.layers);
            this.layers = new ArrayList<>(); // 清空现有的List
        });
        
        return this;
    }
    
    /**
     * 添加一绘图面板(默认坐标变换)
     * @param width 面板宽度
     * @param height 面板高度
     * @return GGplot
     */
    public GGplot addPanel(int width, int height) {
        return this.addPanel(width, height, null);
    }

    /**
     * 图形输出
     * 
     * @param mode plot模式
     * @return BufferedImage
     */
    public BufferedImage print(PlotMode mode) {
        if (this.layers.size() > 0) { // 添加一个绘图面板
            final var w = 1000; // 绘图宽度
            final var h = w / 2; // 绘图高度
            this.addPanel(1000, 500, NVec.of(1, 1, w / 2, h / 2));
        }
        
        return plotFrame.print(dataframe,mode);
    }
    
    /**
     * 图形输出
     * 
     * @return
     */
    public BufferedImage print() {
        return this.print(PlotMode.GRID);
    }

    public int[] default_clr = new int[] { 255, 0, 0 };
    public static GGplot ggplot(DFrame dataframe) {
        return new GGplot(dataframe);
    }

    public static GGplot ggplot() {
        return new GGplot(null);
    }

    private PanelFrame plotFrame = new PanelFrame();
    private DFrame dataframe;
    private List<Layer> layers = new ArrayList<Layer>();

}
